<?php
/**
 * Created by PhpStorm.
 * User: zhangyawen
 * Date: 2021/6/28
 * Time: 5:19 PM
 */
declare(strict_types=1);

namespace App\Service\DataService;


class BaseDS
{
    protected $model;

    public function total(array $where = [], array $group = [], string $field = '')
    {
        $query = $this->model->newQuery();

        !empty($where) && $query = $this->setWhere($where, $query);

        if (!empty($group)) {
            $query = $this->setGroup($query, $group);
        }

        if ($field) {
            return $query->count($field);
        }
        $res = $query->count();

        return $res;
    }

    /**
     * @param array $where ['id'=>1,'name'=>2]
     * @param int $page 分页参数
     * @param int $limit 每页大小 为0则不分页
     * @param array $order  ['created_at' => 'DESC', 'channel_id' => 'ASC']
     * @param array $fields ['channel_id', 'channel_type', 'channel_name']
     * @param array $group ['channel_type', 'channel_name']
     * @return array
     */
    public function list(array $where = [], int $page = 1, int $limit = 0, array $order = [], array $fields = ['*'], array $group = [])
    {
        $query = $this->model->newQuery();
        !empty($where) && $query = $this->setWhere($where, $query);

        !empty($limit) && $query->forPage($page, $limit);

        !empty($order) && $this->setOrder($query, $order);
        if (!empty($group)) {
            $query = $this->setGroup($query, $group);
        }
        return $this->_toArray($query->get($fields));
    }

    protected function setWhere(array $where, $query)
    {
        if (empty($where)) return $query;
        $where_like = [];
        foreach ($where as $field => $value) {
            if (!is_array($value)) {
                $query->where($field, $value);
                continue;
            }
            $operate       = array_keys($value)[0];//得到操作数
            $operate_value = $value[$operate];
            switch (strtolower($operate)) {
                case "like":
                    $where_like[$field] = $operate_value;
                    break;
                case "between":
                    $query->whereBetween($field, $operate_value);
                    break;
                case "wherein":
                    $query->whereIn($field, $operate_value);
                    break;
                case "wherenotin":
                    $query->whereNotIn($field, $operate_value);
                    break;
                case "wherenotnull":
                    $query->whereNotNull($field);
                    break;
                case "wherenull":
                    $query->whereNull($field);
                    break;
                case  "noequalempty":
                    $query->where($field, '!=', '');
                    break;
                case  "neq":
                    $query->where($field, '!=', $operate_value);
                    break;
                case "orwhere":
                    $query->orWhere($field, $operate_value);
                    break;
                case "or":
                    $query->where(function ($query) use ($field, $operate_value) {
                        foreach ($operate_value as $k => $v) {
                            $query->orWhere($field, $v);
                        }
                    });
                    break;
                case "orwherein":
                    $query->orWhereIn($field, $operate_value);
                    break;
                case "whererange":
                    $start = array_shift($operate_value);
                    $end   = array_shift($operate_value);
                    $query->where($field, $start[0], $start[1]);
                    $query->where($field, $end[0], $end[1]);
                    break;
                default:
                    $query->where($field, $operate, $operate_value);
            }
        }
        if (!empty($where_like)) {
            $query->where(function ($query) use ($where_like) {
                foreach ($where_like as $k => $v) {
                    $query->orWhere($k, 'like', "%$v%");
                }
            });
        }
        return $query;
    }

    protected function setGroup($query, array $group = [])
    {
        foreach ($group as $item) {
            $query->groupBy($item);
        }

        return $query;
    }

    protected function setOrder($query, array $order = [])
    {
        if (!empty($order)) {
            foreach ($order as $k => $item) {
                if (is_array($item)) {
                    foreach ($item as $key => $val) {
                        $query->orderBy($key, $val);
                    }
                } else {
                    $query->orderBy($k, $item);
                }
            }
        }

        return $query;
    }

    protected function _toArray($rs)
    {
        return empty($rs) ? [] : $rs->toArray();
    }
}